<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>React 与 Antd 开发前端页面 | 小熊的技术文档</title>
    <meta name="generator" content="VuePress 1.8.2">
    <link rel="icon" href="/fav.ico">
    <link rel="stylesheet" href="/css/katex.min.css">
    <link rel="stylesheet" href="/css/github-markdown.min.css">
    <meta name="description" content="衣带渐宽终不悔，为伊消得人憔悴">
    
    <link rel="preload" href="/assets/css/0.styles.e6449353.css" as="style"><link rel="preload" href="/assets/js/app.9e067b79.js" as="script"><link rel="preload" href="/assets/js/2.983eb755.js" as="script"><link rel="preload" href="/assets/js/18.3af7782b.js" as="script"><link rel="prefetch" href="/assets/js/10.79548333.js"><link rel="prefetch" href="/assets/js/11.31600f80.js"><link rel="prefetch" href="/assets/js/12.62bd3528.js"><link rel="prefetch" href="/assets/js/13.de8b1ace.js"><link rel="prefetch" href="/assets/js/14.f5db1e75.js"><link rel="prefetch" href="/assets/js/15.bf827d4d.js"><link rel="prefetch" href="/assets/js/16.cc9a1a73.js"><link rel="prefetch" href="/assets/js/17.2cfaefeb.js"><link rel="prefetch" href="/assets/js/19.639f7e7b.js"><link rel="prefetch" href="/assets/js/20.dc862f59.js"><link rel="prefetch" href="/assets/js/21.916e1685.js"><link rel="prefetch" href="/assets/js/22.d7a955f4.js"><link rel="prefetch" href="/assets/js/23.078391ef.js"><link rel="prefetch" href="/assets/js/24.bb460a5a.js"><link rel="prefetch" href="/assets/js/25.d69f2326.js"><link rel="prefetch" href="/assets/js/26.6da7ea48.js"><link rel="prefetch" href="/assets/js/27.82e23d91.js"><link rel="prefetch" href="/assets/js/28.9073bbec.js"><link rel="prefetch" href="/assets/js/29.639259a4.js"><link rel="prefetch" href="/assets/js/3.e594e5b2.js"><link rel="prefetch" href="/assets/js/30.b49c622d.js"><link rel="prefetch" href="/assets/js/31.92f6c8b3.js"><link rel="prefetch" href="/assets/js/32.42419088.js"><link rel="prefetch" href="/assets/js/33.c82e2ab8.js"><link rel="prefetch" href="/assets/js/34.381de37e.js"><link rel="prefetch" href="/assets/js/35.5e86d478.js"><link rel="prefetch" href="/assets/js/36.31f218ce.js"><link rel="prefetch" href="/assets/js/37.0d287b3f.js"><link rel="prefetch" href="/assets/js/38.1324cf44.js"><link rel="prefetch" href="/assets/js/39.de6bdb51.js"><link rel="prefetch" href="/assets/js/4.440c4dd9.js"><link rel="prefetch" href="/assets/js/40.a22c9c27.js"><link rel="prefetch" href="/assets/js/41.4637d617.js"><link rel="prefetch" href="/assets/js/42.db815e2b.js"><link rel="prefetch" href="/assets/js/43.f0955a92.js"><link rel="prefetch" href="/assets/js/44.7d5faddf.js"><link rel="prefetch" href="/assets/js/45.a88ffc33.js"><link rel="prefetch" href="/assets/js/46.883caa71.js"><link rel="prefetch" href="/assets/js/47.6f2cfd60.js"><link rel="prefetch" href="/assets/js/48.ea25654e.js"><link rel="prefetch" href="/assets/js/49.f38c23a0.js"><link rel="prefetch" href="/assets/js/5.e8844f36.js"><link rel="prefetch" href="/assets/js/50.e03dd8e9.js"><link rel="prefetch" href="/assets/js/51.f6160d52.js"><link rel="prefetch" href="/assets/js/52.4daa8322.js"><link rel="prefetch" href="/assets/js/53.b30992e9.js"><link rel="prefetch" href="/assets/js/54.209f17e1.js"><link rel="prefetch" href="/assets/js/55.4f1dd95b.js"><link rel="prefetch" href="/assets/js/56.147ea3e8.js"><link rel="prefetch" href="/assets/js/57.5823e0e2.js"><link rel="prefetch" href="/assets/js/58.772320f9.js"><link rel="prefetch" href="/assets/js/59.5ab55a80.js"><link rel="prefetch" href="/assets/js/6.54e1cc95.js"><link rel="prefetch" href="/assets/js/60.b47b75bb.js"><link rel="prefetch" href="/assets/js/61.0cd5a012.js"><link rel="prefetch" href="/assets/js/62.35eb5453.js"><link rel="prefetch" href="/assets/js/63.d31f2118.js"><link rel="prefetch" href="/assets/js/64.03d35d7c.js"><link rel="prefetch" href="/assets/js/65.8bdc633f.js"><link rel="prefetch" href="/assets/js/66.dbbe8867.js"><link rel="prefetch" href="/assets/js/67.228613b5.js"><link rel="prefetch" href="/assets/js/68.d10a2687.js"><link rel="prefetch" href="/assets/js/69.7903847f.js"><link rel="prefetch" href="/assets/js/7.f5ab00eb.js"><link rel="prefetch" href="/assets/js/70.11ee4e27.js"><link rel="prefetch" href="/assets/js/8.95b39934.js"><link rel="prefetch" href="/assets/js/9.26cfd48c.js">
    <link rel="stylesheet" href="/assets/css/0.styles.e6449353.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">小熊的技术文档</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/front-end/" class="nav-link router-link-active">
  🎨前端
</a></div><div class="nav-item"><a href="/back-end/" class="nav-link">
  💻后端
</a></div><div class="nav-item"><a href="/practice/" class="nav-link">
  🚀实战
</a></div><div class="nav-item"><a href="/office/" class="nav-link">
  🏢办公
</a></div><div class="nav-item"><a href="/general/" class="nav-link">
  🍓通用
</a></div><div class="nav-item"><a href="/paper/" class="nav-link">
  🐸论文
</a></div><div class="nav-item"><a href="/general/fast.html" class="nav-link">
  ⚡快速笔记
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="🦉近期重点" class="dropdown-title"><span class="title">🦉近期重点</span> <span class="arrow down"></span></button> <button type="button" aria-label="🦉近期重点" class="mobile-dropdown-title"><span class="title">🦉近期重点</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/back-end/python.html" class="nav-link">
  🐇python常用模块
</a></li><li class="dropdown-item"><!----> <a href="/practice/zrender.html" class="nav-link">
  🌹zrender源码解析
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="⭐️资源" class="dropdown-title"><span class="title">⭐️资源</span> <span class="arrow down"></span></button> <button type="button" aria-label="⭐️资源" class="mobile-dropdown-title"><span class="title">⭐️资源</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://www.birdiesearch.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  小鸟搜索
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://salttiger.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  每天一本编程书
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://gitee.com/docmirror/dev-sidecar" target="_blank" rel="noopener noreferrer" class="nav-link external">
  开发者边车
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/front-end/" class="nav-link router-link-active">
  🎨前端
</a></div><div class="nav-item"><a href="/back-end/" class="nav-link">
  💻后端
</a></div><div class="nav-item"><a href="/practice/" class="nav-link">
  🚀实战
</a></div><div class="nav-item"><a href="/office/" class="nav-link">
  🏢办公
</a></div><div class="nav-item"><a href="/general/" class="nav-link">
  🍓通用
</a></div><div class="nav-item"><a href="/paper/" class="nav-link">
  🐸论文
</a></div><div class="nav-item"><a href="/general/fast.html" class="nav-link">
  ⚡快速笔记
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="🦉近期重点" class="dropdown-title"><span class="title">🦉近期重点</span> <span class="arrow down"></span></button> <button type="button" aria-label="🦉近期重点" class="mobile-dropdown-title"><span class="title">🦉近期重点</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/back-end/python.html" class="nav-link">
  🐇python常用模块
</a></li><li class="dropdown-item"><!----> <a href="/practice/zrender.html" class="nav-link">
  🌹zrender源码解析
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="⭐️资源" class="dropdown-title"><span class="title">⭐️资源</span> <span class="arrow down"></span></button> <button type="button" aria-label="⭐️资源" class="mobile-dropdown-title"><span class="title">⭐️资源</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://www.birdiesearch.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  小鸟搜索
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://salttiger.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  每天一本编程书
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://gitee.com/docmirror/dev-sidecar" target="_blank" rel="noopener noreferrer" class="nav-link external">
  开发者边车
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav>  <ul class="sidebar-links"><li><a href="/front-end/javascript.html" class="sidebar-link">Javascript/ECMAScript 相关技术</a></li><li><a href="/front-end/pattern.html" class="sidebar-link">前端设计模式</a></li><li><a href="/front-end/typescript.html" class="sidebar-link">学习 Typescript 实战开发</a></li><li><a href="/front-end/es6.html" class="sidebar-link">深入理解ES6</a></li><li><a href="/front-end/css.html" class="sidebar-link">css 实战学习</a></li><li><a href="/front-end/node.html" class="sidebar-link">Node.js深入浅出</a></li><li><a href="/front-end/design.html" class="sidebar-link">前端设计与可视化</a></li><li><a href="/front-end/npm.html" class="sidebar-link">npm中常用命令与模块</a></li><li><a href="/front-end/vuepress.html" class="sidebar-link">vuepress 基本配置</a></li><li><a href="/front-end/babel.html" class="sidebar-link">Babel详细学习</a></li><li><a href="/front-end/vue.html" class="sidebar-link">Vue项目实战</a></li><li><a href="/front-end/react.html" class="sidebar-link">React17+React Hook+TS4 最佳实践</a></li><li><a href="/front-end/electron.html" class="sidebar-link">electron实战</a></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="react-与-antd-开发前端页面"><a href="#react-与-antd-开发前端页面" class="header-anchor">#</a> React 与 Antd 开发前端页面</h1> <h2 id="react-安装"><a href="#react-安装" class="header-anchor">#</a> React 安装</h2> <p>React 生态: React + React-Router + Redux + Axios + Babel + Webpack<br>
React 是声明式实现, 使用 yarn, 通过<code>npm install yarn -g</code>安装 yarn 最新稳定版本.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 初始化项目</span>
yarn init
<span class="token comment">// 新增包</span>
yarn add
<span class="token comment">// 删除包</span>
yarn remove
<span class="token comment">// 安装项目所有依赖</span>
yarn <span class="token operator">/</span> yarn install
</code></pre></div><p>使用命令初始化项目<code>npx create-react-app my-antd</code>, 如果项目运行不起来, 考虑是不是上层文件夹有没有<code>node_modules</code>文件夹, 否则会报错.<br>
默认 react 会启用严格模式 StrictMode,StrictMode 是一个用来突出显示应用程序中潜在问题的工具。严格模式检查仅在开发模式下运行, StrictMode 目前有助于：</p> <ul><li>识别不安全的生命周期</li> <li>关于使用过时字符串 ref API 的警告</li> <li>关于使用废弃的 findDOMNode 方法的警告</li> <li>检测意外的副作用</li> <li>检测过时的 context API</li></ul> <h2 id="首页开发"><a href="#首页开发" class="header-anchor">#</a> 首页开发</h2> <h3 id="增加-less-支持"><a href="#增加-less-支持" class="header-anchor">#</a> 增加 less 支持</h3> <p>安装依赖:<code>yarn add react-router-dom@4.2.2 axios less@2.7.3 less-loader@4.1.0 --save</code>, 其中<code>less</code>和<code>less-loader</code>都需要安装.</p> <p>然后运行<code>yarn eject</code>暴露原本的<code>webpack</code>设置, 暴露之前需要使用 git 保存当前情况, 否则运行 eject 会报错.<br>
在<code>config/webpack.config.js</code>的配置文件汇总, 在<code>module.rules</code>下面的<code>oneOf:[]</code>数组中, 仿照<code>cssRegex</code>增加<code>less</code>解析器, 如下所示:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token punctuation">{</span>
  test<span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.less$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  exclude<span class="token operator">:</span> cssModuleRegex<span class="token punctuation">,</span>
  use<span class="token operator">:</span> <span class="token function">getStyleLoaders</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    importLoaders<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
    sourceMap<span class="token operator">:</span> isEnvProduction <span class="token operator">&amp;&amp;</span> shouldUseSourceMap<span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token comment">// Don't consider CSS imports dead code even if the</span>
  <span class="token comment">// containing package claims to have no side effects.</span>
  <span class="token comment">// Remove this when webpack adds a warning or an error for this.</span>
  <span class="token comment">// See https://github.com/webpack/webpack/issues/6571</span>
  sideEffects<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
</code></pre></div><p>由于<code>use</code>中调用的是<code>getStyleLoaders</code>函数, 因此还需要修改<code>getStyleLoaders</code>, 在<code>loaders</code>变量的最后增加</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token punctuation">{</span>
  loader<span class="token operator">:</span> require<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">'less-loader'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
</code></pre></div><p>因为 loaders 是从后向前解析的, 所以需要加在最开头, 先解析 less, 然后在解析 css 等</p> <h3 id="实现按需加载"><a href="#实现按需加载" class="header-anchor">#</a> 实现按需加载</h3> <p>antd 官网提供了<a href="https://ant.design/docs/react/getting-started-cn#%E6%8C%89%E9%9C%80%E5%8A%A0%E8%BD%BD" target="_blank" rel="noopener noreferrer">按需加载<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>的说明, 首先需要安装<code>npm install babel-plugin-import --save-dev</code>, 然后修改配置, 这里我们直接在<code>webpack</code>中进行修改, 修改的地方位于系统调用<code>babel-loader</code>时, 即<code>loader: require.resolve('babel-loader')</code>, 此时在插件栏中加入<code>['import', { libraryName: 'antd', style: true }]</code>, 即可实现按需加载 css, 不需要在页面中再写<code>import css</code></p> <div class="language-js extra-class"><pre class="language-js"><code>
<span class="token punctuation">{</span>
  test<span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(js|mjs|jsx|ts|tsx)$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  include<span class="token operator">:</span> paths<span class="token punctuation">.</span>appSrc<span class="token punctuation">,</span>
  loader<span class="token operator">:</span> require<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">'babel-loader'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  options<span class="token operator">:</span> <span class="token punctuation">{</span>
    customize<span class="token operator">:</span> require<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>
      <span class="token string">'babel-preset-react-app/webpack-overrides'</span>
    <span class="token punctuation">)</span><span class="token punctuation">,</span>
    plugins<span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token punctuation">[</span>
        require<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">'babel-plugin-named-asset-import'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
          loaderMap<span class="token operator">:</span> <span class="token punctuation">{</span>
            svg<span class="token operator">:</span> <span class="token punctuation">{</span>
              ReactComponent<span class="token operator">:</span>
                <span class="token string">'@svgr/webpack?-svgo,+titleProp,+ref![path]'</span><span class="token punctuation">,</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token comment">// 下面是增加的, 实现按需导入</span>
      <span class="token punctuation">[</span><span class="token string">'import'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> libraryName<span class="token operator">:</span> <span class="token string">'antd'</span><span class="token punctuation">,</span> style<span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    cacheDirectory<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
    cacheCompression<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
    compact<span class="token operator">:</span> isEnvProduction<span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
            <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token template-punctuation string">`</span></span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
### 使用 aliyun 主题

在</span><span class="token template-punctuation string">`</span></span>config<span class="token operator">/</span>webpack<span class="token punctuation">.</span>config<span class="token punctuation">.</span>js<span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">的 less-loader 配置中, 利用</span><span class="token template-punctuation string">`</span></span>modifyVars<span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">修改相应变量, 即可改变主题颜色.

</span><span class="token template-punctuation string">`</span></span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token template-punctuation string">`</span></span>js
<span class="token punctuation">{</span>
  loader<span class="token operator">:</span> <span class="token string">'less-loader'</span><span class="token punctuation">,</span>
  options<span class="token operator">:</span> <span class="token punctuation">{</span>
    modules<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
    modifyVars<span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token string">'@font-size-sm'</span><span class="token operator">:</span> <span class="token string">'12px'</span><span class="token punctuation">,</span>
      <span class="token string">'@font-size-base'</span><span class="token operator">:</span> <span class="token string">'12px'</span><span class="token punctuation">,</span>
      <span class="token string">'@primary-color'</span><span class="token operator">:</span> <span class="token string">'#0070cc'</span><span class="token punctuation">,</span>
      <span class="token string">'@border-radius-base'</span><span class="token operator">:</span> <span class="token string">'0'</span><span class="token punctuation">,</span>
      <span class="token string">'@border-radius-sm'</span><span class="token operator">:</span> <span class="token string">'0'</span><span class="token punctuation">,</span>
      <span class="token string">'@text-color'</span><span class="token operator">:</span> <span class="token string">'fade(#000, 65%)'</span><span class="token punctuation">,</span>
      <span class="token string">'@text-color-secondary'</span><span class="token operator">:</span> <span class="token string">'fade(#000, 45%)'</span><span class="token punctuation">,</span>
      <span class="token string">'@background-color-base'</span><span class="token operator">:</span> <span class="token string">'hsv(0, 0, 96%)'</span><span class="token punctuation">,</span>
      <span class="token string">'@success-color'</span><span class="token operator">:</span> <span class="token string">'#1e8e3e'</span><span class="token punctuation">,</span>
      <span class="token string">'@error-color'</span><span class="token operator">:</span> <span class="token string">'#d93026'</span><span class="token punctuation">,</span>
      <span class="token string">'@warning-color'</span><span class="token operator">:</span> <span class="token string">'#ffc440'</span><span class="token punctuation">,</span>
      <span class="token string">'@info-color'</span><span class="token operator">:</span> <span class="token string">'@primary-color'</span><span class="token punctuation">,</span>
      <span class="token string">'@danger-color'</span><span class="token operator">:</span> <span class="token string">'@error-color'</span><span class="token punctuation">,</span>
      <span class="token string">'@processing-color'</span><span class="token operator">:</span> <span class="token string">'@primary-color'</span><span class="token punctuation">,</span>
      <span class="token string">'@border-color-base'</span><span class="token operator">:</span> <span class="token string">'#dedede'</span><span class="token punctuation">,</span>
      <span class="token string">'@border-color-split'</span><span class="token operator">:</span> <span class="token string">'#dedede'</span><span class="token punctuation">,</span>
      <span class="token string">'@outline-width'</span><span class="token operator">:</span> <span class="token string">'0'</span><span class="token punctuation">,</span>
      <span class="token string">'@outline-color'</span><span class="token operator">:</span> <span class="token string">'#737373'</span><span class="token punctuation">,</span>
      <span class="token string">'@input-height-lg'</span><span class="token operator">:</span> <span class="token string">'36px'</span><span class="token punctuation">,</span>
      <span class="token string">'@input-height-base'</span><span class="token operator">:</span> <span class="token string">'32px'</span><span class="token punctuation">,</span>
      <span class="token string">'@input-height-sm'</span><span class="token operator">:</span> <span class="token string">'24px'</span><span class="token punctuation">,</span>
      <span class="token string">'@input-hover-border-color'</span><span class="token operator">:</span> <span class="token string">'#737373'</span><span class="token punctuation">,</span>
      <span class="token string">'@form-item-margin-bottom'</span><span class="token operator">:</span> <span class="token string">'16px'</span><span class="token punctuation">,</span>
      <span class="token string">'@btn-default-bg'</span><span class="token operator">:</span> <span class="token string">'#fafafa'</span><span class="token punctuation">,</span>
      <span class="token string">'@btn-default-border'</span><span class="token operator">:</span> <span class="token string">'#dedede'</span><span class="token punctuation">,</span>
      <span class="token string">'@btn-danger-color'</span><span class="token operator">:</span> <span class="token string">'#fff'</span><span class="token punctuation">,</span>
      <span class="token string">'@btn-danger-bg'</span><span class="token operator">:</span> <span class="token string">'@error-color'</span><span class="token punctuation">,</span>
      <span class="token string">'@btn-danger-border'</span><span class="token operator">:</span> <span class="token string">'@error-color'</span><span class="token punctuation">,</span>
      <span class="token string">'@switch-color'</span><span class="token operator">:</span> <span class="token string">'@success-color'</span><span class="token punctuation">,</span>
      <span class="token string">'@table-header-bg'</span><span class="token operator">:</span> <span class="token string">'#fafafa'</span><span class="token punctuation">,</span>
      <span class="token string">'@table-row-hover-bg'</span><span class="token operator">:</span> <span class="token string">'#fafafa'</span><span class="token punctuation">,</span>
      <span class="token string">'@table-padding-vertical'</span><span class="token operator">:</span> <span class="token string">'15px'</span><span class="token punctuation">,</span>
      <span class="token string">'@badge-color'</span><span class="token operator">:</span> <span class="token string">'@error-color'</span><span class="token punctuation">,</span>
      <span class="token string">'@breadcrumb-base-color'</span><span class="token operator">:</span> <span class="token string">'@text-color'</span><span class="token punctuation">,</span>
      <span class="token string">'@breadcrumb-last-item-color'</span><span class="token operator">:</span> <span class="token string">'@text-color-secondary'</span><span class="token punctuation">,</span>
      <span class="token string">'@slider-rail-background-color'</span><span class="token operator">:</span> <span class="token string">'@background-color-base'</span><span class="token punctuation">,</span>
      <span class="token string">'@slider-rail-background-color-hover'</span><span class="token operator">:</span> <span class="token string">'#e1e1e1'</span><span class="token punctuation">,</span>
      <span class="token string">'@slider-track-background-color'</span><span class="token operator">:</span> <span class="token string">'@primary-color'</span><span class="token punctuation">,</span>
      <span class="token string">'@slider-track-background-color-hover'</span><span class="token operator">:</span> <span class="token string">'@primary-color'</span><span class="token punctuation">,</span>
      <span class="token string">'@slider-handle-border-width'</span><span class="token operator">:</span> <span class="token string">'1px'</span><span class="token punctuation">,</span>
      <span class="token string">'@slider-handle-color'</span><span class="token operator">:</span> <span class="token string">'#dedede'</span><span class="token punctuation">,</span>
      <span class="token string">'@slider-handle-color-hover'</span><span class="token operator">:</span> <span class="token string">'#dedede'</span><span class="token punctuation">,</span>
      <span class="token string">'@slider-handle-color-focus'</span><span class="token operator">:</span> <span class="token string">'#dedede'</span><span class="token punctuation">,</span>
      <span class="token string">'@slider-handle-color-tooltip-open'</span><span class="token operator">:</span> <span class="token string">'#ddd'</span><span class="token punctuation">,</span>
      <span class="token string">'@slider-handle-color-focus-shadow'</span><span class="token operator">:</span> <span class="token string">'transparent'</span><span class="token punctuation">,</span>
      <span class="token string">'@slider-handle-shadow'</span><span class="token operator">:</span> <span class="token string">'1px 1px 4px 0 rgba(0,0,0,.13)'</span><span class="token punctuation">,</span>
      <span class="token string">'@alert-success-border-color'</span><span class="token operator">:</span> <span class="token string">'#dff4e5'</span><span class="token punctuation">,</span>
      <span class="token string">'@alert-success-bg-color'</span><span class="token operator">:</span> <span class="token string">'#dff4e5'</span><span class="token punctuation">,</span>
      <span class="token string">'@alert-info-border-color'</span><span class="token operator">:</span> <span class="token string">'#e5f3ff'</span><span class="token punctuation">,</span>
      <span class="token string">'@alert-info-bg-color'</span><span class="token operator">:</span> <span class="token string">'#e5f3ff'</span><span class="token punctuation">,</span>
      <span class="token string">'@alert-error-border-color'</span><span class="token operator">:</span> <span class="token string">'#fcebea'</span><span class="token punctuation">,</span>
      <span class="token string">'@alert-error-bg-color'</span><span class="token operator">:</span> <span class="token string">'#fcebea'</span><span class="token punctuation">,</span>
      <span class="token string">'@alert-warning-border-color'</span><span class="token operator">:</span> <span class="token string">'#fff7db'</span><span class="token punctuation">,</span>
      <span class="token string">'@alert-warning-bg-color'</span><span class="token operator">:</span> <span class="token string">'#fff7db'</span><span class="token punctuation">,</span>
      <span class="token string">'@radio-button-bg'</span><span class="token operator">:</span> <span class="token string">'transparent'</span><span class="token punctuation">,</span>
      <span class="token string">'@radio-button-checked-bg'</span><span class="token operator">:</span> <span class="token string">'transparent'</span><span class="token punctuation">,</span>
      <span class="token string">'@progress-radius'</span><span class="token operator">:</span> <span class="token string">'0'</span><span class="token punctuation">,</span>
      <span class="token string">'@tabs-card-gutter'</span><span class="token operator">:</span> <span class="token string">'-1px'</span><span class="token punctuation">,</span>
      <span class="token string">'@tabs-card-tab-active-border-top'</span><span class="token operator">:</span> <span class="token string">'2px solid @primary-color'</span><span class="token punctuation">,</span>
      <span class="token string">'@layout-body-background'</span><span class="token operator">:</span> <span class="token string">'#fafafa'</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="添加装饰器支持"><a href="#添加装饰器支持" class="header-anchor">#</a> 添加装饰器支持</h3> <p>首先安装 babel 的装饰器支持插件<code>yarn add @babel/plugin-proposal-decorators</code></p> <p>将项目中 package.json 中的 babel 依赖修改为：</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token property">&quot;babel&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">&quot;plugins&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token punctuation">[</span>
        <span class="token string">&quot;@babel/plugin-proposal-decorators&quot;</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
          <span class="token property">&quot;legacy&quot;</span><span class="token operator">:</span> <span class="token boolean">true</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">]</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token property">&quot;presets&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token string">&quot;react-app&quot;</span>
    <span class="token punctuation">]</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
</code></pre></div><p>这样就可以使用装饰器语法了.</p> <h2 id="使用状态管理-mobx-插件"><a href="#使用状态管理-mobx-插件" class="header-anchor">#</a> 使用状态管理 mobx 插件</h2> <blockquote><p>MobX 是一个简单、方便扩展、久经考验的状态管理解决方案.</p></blockquote> <h3 id="核心思想"><a href="#核心思想" class="header-anchor">#</a> 核心思想</h3> <p>状态是每个应用程序的核心，没有比创建不一致的状态或与徘徊的局部变量不同步的状态更快的方法来创建有缺陷的，难以管理的应用程序。因此，许多状态管理解决方案试图限制修改状态的方式，例如通过使状态不可变。但这带来了新的问题。数据需要规范化，无法再确保参照完整性，因此使用功能强大的概念（例如原型）几乎变得不可能。</p> <p>MobX 通过解决根本问题而使状态管理再次变得简单：它使得不可能产生不一致的状态。实现这一目标的策略很简单： 确保所有可以从应用程序状态派生的内容都将被自动派生。</p> <p>从概念上讲，MobX 将您的应用程序视为电子表格。<br> <img src="https://s1.ax1x.com/2020/05/03/YpSR8H.png" alt="mobx核心思想"></p> <ol><li>首先，存在应用程序状态。对象，数组，基元，引用的图形构成了应用程序的模型。这些值是应用程序的“数据单元”。</li> <li>其次是推导。基本上，任何可以根据应用程序状态自动计算的值。这些派生值或计算值的范围从简单的值（例如待办事项的数量）到复杂的东西（如待办事项的可视 HTML 表示）。用电子表格术语：这些是您的应用程序的公式和图表。</li> <li>反应与推导非常相似。主要区别在于这些函数不会产生值。相反，它们会自动运行以执行某些任务。通常，这与 I / O 有关。他们确保 DOM 更新或在正确的时间自动发出网络请求。</li> <li>最后有动作。行动是改变状态的一切。MobX 将确保由您的操作引起的对应用程序状态的所有更改都将被所有派生和反应自动处理。同步且无故障。</li></ol> <h3 id="待办事项示例"><a href="#待办事项示例" class="header-anchor">#</a> 待办事项示例</h3> <p>在没有用 mobx 的时候实现待办事项的储存, 示例代码如下</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">class</span> <span class="token class-name">TodoStore</span> <span class="token punctuation">{</span>
  todos <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">// 内部属性, 存储所有的待办事项</span>

  <span class="token comment">// 获得已经完成的待办事项数量</span>
  <span class="token keyword">get</span> <span class="token function">completedTodosCount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>todos<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">todo</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> todo<span class="token punctuation">.</span>completed <span class="token operator">===</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">.</span>length
  <span class="token punctuation">}</span>
  <span class="token comment">// 报告当前的待办事项情况</span>
  <span class="token function">report</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>todos<span class="token punctuation">.</span>length <span class="token operator">===</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token string">'&lt;无&gt;'</span>
    <span class="token keyword">const</span> nextTodo <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>todos<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">todo</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> todo<span class="token punctuation">.</span>completed <span class="token operator">===</span> <span class="token boolean">false</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span>
      <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">下一个事项: &quot;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>nextTodo <span class="token operator">?</span> nextTodo<span class="token punctuation">.</span>task <span class="token operator">:</span> <span class="token string">'&lt;无&gt;'</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&quot;. </span><span class="token template-punctuation string">`</span></span> <span class="token operator">+</span>
      <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">当前进度: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>completedTodosCount<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>todos<span class="token punctuation">.</span>length<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span>
    <span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token comment">// 增加待办事项, 默认completed(完成)为否,assignee(委托人)为空</span>
  <span class="token function">addTodo</span><span class="token punctuation">(</span><span class="token parameter">task</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>todos<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      task<span class="token operator">:</span> task<span class="token punctuation">,</span>
      completed<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
      assignee<span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// 新建待办事项储存实例</span>
<span class="token keyword">const</span> todoStore <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">TodoStore</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre></div><p>我们刚刚创建了一个 带有 <code>todos</code>集合的<code>todoStore</code>的实例。是时候用一些对象填充<code>todoStore</code>了。为了确保我们看到更改的效果，我们 <code>todoStore.report</code>方法在每次更改后调用并记录下来。请注意，报表有意始终仅打印第一个任务。它使该示例有些虚假，但是正如您将在下面看到的那样，它很好地证明了 MobX 的依赖项跟踪是动态的。</p> <div class="language-js extra-class"><pre class="language-js"><code>todoStore<span class="token punctuation">.</span><span class="token function">addTodo</span><span class="token punctuation">(</span><span class="token string">'read MobX tutorial'</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>todoStore<span class="token punctuation">.</span><span class="token function">report</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 输出:下一个事项: &quot;read MobX tutorial&quot;. 当前进度: 0/1</span>

todoStore<span class="token punctuation">.</span><span class="token function">addTodo</span><span class="token punctuation">(</span><span class="token string">'try MobX'</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>todoStore<span class="token punctuation">.</span><span class="token function">report</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 输出:下一个事项: &quot;read MobX tutorial&quot;. 当前进度: 0/2</span>

todoStore<span class="token punctuation">.</span>todos<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>completed <span class="token operator">=</span> <span class="token boolean">true</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>todoStore<span class="token punctuation">.</span><span class="token function">report</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 输出: 下一个事项: &quot;try MobX&quot;. 当前进度: 1/2</span>

todoStore<span class="token punctuation">.</span>todos<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>task <span class="token operator">=</span> <span class="token string">'try MobX in own project'</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>todoStore<span class="token punctuation">.</span><span class="token function">report</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 输出: 下一个事项: &quot;try MobX in own project&quot;. 当前进度: 1/2</span>

todoStore<span class="token punctuation">.</span>todos<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>task <span class="token operator">=</span> <span class="token string">'grok MobX tutorial'</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>todoStore<span class="token punctuation">.</span><span class="token function">report</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 输出: 下一个事项: &quot;try MobX in own project&quot;. 当前进度: 1/2</span>
</code></pre></div><h3 id="变成响应式"><a href="#变成响应式" class="header-anchor">#</a> 变成响应式</h3> <p>到目前为止，此代码没有什么特别的。但是，如果我们不必显式调用<code>report()</code> ，而可以声明我们希望在每次状态更改时调用它呢？这将使我们免于从代码库中可能影响报告的任何位置进行调用<code>report()</code>的责任。我们希望确保已打印最新报告。但是我们不想被组织起来打扰。</p> <p>幸运的是，这正是 <code>MobX</code> 可以为您做的。自动执行仅取决于状态的代码。这样我们的<code>report()``功能就可以自动更新，就像电子表格中的图表一样。为此，TodoStore</code> 必须变得可观察，以便 <code>MobX</code> 可以跟踪所有正在进行的更改。让我们更改类以使其达到目的。</p> <p>同样，该 <code>completedTodosCount</code> 属性可以自动从待办事项列表中派生。通过使用<code>@observable</code> 和<code>@computed</code> 装饰器，我们可以在对象上引入可观察的属性：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">class</span> <span class="token class-name">ObservableTodoStore</span> <span class="token punctuation">{</span>
  @observable todos <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
  @observable pendingRequests <span class="token operator">=</span> <span class="token number">0</span>

  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    mobx<span class="token punctuation">.</span><span class="token function">autorun</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>report<span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  @computed <span class="token keyword">get</span> <span class="token function">completedTodosCount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>todos<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">todo</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> todo<span class="token punctuation">.</span>completed <span class="token operator">===</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">.</span>length
  <span class="token punctuation">}</span>

  @computed <span class="token keyword">get</span> <span class="token function">report</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>todos<span class="token punctuation">.</span>length <span class="token operator">===</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token string">'&lt;无&gt;'</span>
    <span class="token keyword">const</span> nextTodo <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>todos<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">todo</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> todo<span class="token punctuation">.</span>completed <span class="token operator">===</span> <span class="token boolean">false</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span>
      <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">下一个待办事项: &quot;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>nextTodo <span class="token operator">?</span> nextTodo<span class="token punctuation">.</span>task <span class="token operator">:</span> <span class="token string">'&lt;无&gt;'</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&quot;. </span><span class="token template-punctuation string">`</span></span> <span class="token operator">+</span>
      <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">当前进度: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>completedTodosCount<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>todos<span class="token punctuation">.</span>length<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span>
    <span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token function">addTodo</span><span class="token punctuation">(</span><span class="token parameter">task</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>todos<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      task<span class="token operator">:</span> task<span class="token punctuation">,</span>
      completed<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
      assignee<span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> observableTodoStore <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ObservableTodoStore</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre></div><p>这就可以了！我们将一些属性标记为<code>@observable</code> 向 MobX 发出信号，这些值可以随时间变化。用<code>@computed</code> 装饰计算式, 计算状态变化后的值。</p> <p>目前还未使用<code>pendingRequests</code>与<code>assignee</code>属性，但将在本教程后面使用。为简洁起见，此页面上的所有示例均使用 ES6，JSX 和装饰器。但是不用担心，MobX 中的所有装饰器都有对应的 ES5。</p> <p>在构造函数中，我们创建了一个小函数，用于打印 report 并将其包装在<code>autorun</code>函数中。<code>autorun</code>函数会创建一个响应，该响应运行一次，然后在该函数内部使用的任何可观察数据发生更改时自动重新运行。因为 report 使用了 observable todos 属性，它将在适当的时候打印报告。在下一个清单中将证明这一点。只需按下运行按钮：</p> <div class="language-js extra-class"><pre class="language-js"><code>observableTodoStore<span class="token punctuation">.</span><span class="token function">addTodo</span><span class="token punctuation">(</span><span class="token string">'读三体1'</span><span class="token punctuation">)</span>
<span class="token comment">// 输出:下一个待办事项: &quot;读三体1&quot;. 当前进度: 0/1</span>
observableTodoStore<span class="token punctuation">.</span><span class="token function">addTodo</span><span class="token punctuation">(</span><span class="token string">'写代码'</span><span class="token punctuation">)</span>
<span class="token comment">// 输出: 下一个待办事项: &quot;读三体1&quot;. 当前进度: 0/2</span>
observableTodoStore<span class="token punctuation">.</span>todos<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>completed <span class="token operator">=</span> <span class="token boolean">true</span>
<span class="token comment">// 输出: 下一个待办事项: &quot;写代码&quot;. 当前进度: 1/2</span>
observableTodoStore<span class="token punctuation">.</span>todos<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>task <span class="token operator">=</span> <span class="token string">'将三体1改为三体2'</span>
<span class="token comment">// 输出: 下一个待办事项: &quot;将三体1改为三体2&quot;. 当前进度: 1/2</span>
observableTodoStore<span class="token punctuation">.</span>todos<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>task <span class="token operator">=</span> <span class="token string">'将写代码改为读代码'</span>
<span class="token comment">// 没有输出</span>
</code></pre></div><p>纯粹的乐趣吧？在 report 没有自动打印，同步，无泄漏中间值。如果仔细调查日志，您将看到第五行没有产生新的日志行。因为重命名实际上并没有改变报告，但是支持数据却改变了。另一方面，更改第一个待办事项的名称确实会更新报告，因为该名称已在报告中积极使用。这很好地证明了不仅 todos 数组正在被观察 autorun，还有待办事项中的各个属性。</p> <h3 id="使-react-反应"><a href="#使-react-反应" class="header-anchor">#</a> 使 React 反应</h3> <p>好的，到目前为止，我们做出了一个愚蠢的报告。是时候在这家同一个商店周围建立反应式用户界面了。尽管有它们的名字，React 组件却是无反应的。包中的@observer 装饰器 mobx-react 通过将 React 组件 render 方法包装在中来修复此问题，该方法 autorun 自动使您的组件与状态保持同步。从概念上讲，这与我们 report 之前所做的没什么不同。</p> <p>下一个清单定义了一些 React 组件。那里唯一的 MobX 东西是@observer 装饰器。这足以确保在相关数据更改时每个组件都单独重新渲染。您无需再调用 setState，也不必弄清楚如何使用选择器或需要配置的高阶组件来订阅应用程序状态的适当部分。基本上，所有组件都变得智能。然而，它们是以愚蠢的声明性方式定义的。</p> <p>按运行代码按钮以查看下面的代码。该列表是可编辑的，因此可以随意使用。例如，尝试删除所有@observer 呼叫，或者仅删除装饰的呼叫 TodoView。每次渲染组件时，右侧预览中的数字都会突出显示。</p> <div class="language-js extra-class"><pre class="language-js"><code>@observer
<span class="token keyword">class</span> <span class="token class-name">TodoList</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>store
    <span class="token keyword">return</span> <span class="token punctuation">(</span>
      <span class="token operator">&lt;</span>div<span class="token operator">&gt;</span>
        <span class="token punctuation">{</span>store<span class="token punctuation">.</span>report<span class="token punctuation">}</span>
        <span class="token operator">&lt;</span>ul<span class="token operator">&gt;</span>
          <span class="token punctuation">{</span>store<span class="token punctuation">.</span>todos<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">todo<span class="token punctuation">,</span> idx</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">(</span>
            <span class="token operator">&lt;</span>TodoView todo<span class="token operator">=</span><span class="token punctuation">{</span>todo<span class="token punctuation">}</span> key<span class="token operator">=</span><span class="token punctuation">{</span>idx<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">&gt;</span>
          <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">}</span>
        <span class="token operator">&lt;</span><span class="token operator">/</span>ul<span class="token operator">&gt;</span>
        <span class="token punctuation">{</span>store<span class="token punctuation">.</span>pendingRequests <span class="token operator">&gt;</span> <span class="token number">0</span> <span class="token operator">?</span> <span class="token operator">&lt;</span>marquee<span class="token operator">&gt;</span>Loading<span class="token operator">...</span><span class="token operator">&lt;</span><span class="token operator">/</span>marquee<span class="token operator">&gt;</span> <span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">}</span>
        <span class="token operator">&lt;</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>onNewTodo<span class="token punctuation">}</span><span class="token operator">&gt;</span>New Todo<span class="token operator">&lt;</span><span class="token operator">/</span>button<span class="token operator">&gt;</span>
        <span class="token operator">&lt;</span>small<span class="token operator">&gt;</span> <span class="token punctuation">(</span>double<span class="token operator">-</span>click a todo to edit<span class="token punctuation">)</span><span class="token operator">&lt;</span><span class="token operator">/</span>small<span class="token operator">&gt;</span>
        <span class="token operator">&lt;</span>RenderCounter <span class="token operator">/</span><span class="token operator">&gt;</span>
      <span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
    <span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token function-variable function">onNewTodo</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>store<span class="token punctuation">.</span><span class="token function">addTodo</span><span class="token punctuation">(</span><span class="token function">prompt</span><span class="token punctuation">(</span><span class="token string">'Enter a new todo:'</span><span class="token punctuation">,</span> <span class="token string">'coffee plz'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

@observer
<span class="token keyword">class</span> <span class="token class-name">TodoView</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> todo <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>todo
    <span class="token keyword">return</span> <span class="token punctuation">(</span>
      <span class="token operator">&lt;</span>li onDoubleClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>onRename<span class="token punctuation">}</span><span class="token operator">&gt;</span>
        <span class="token operator">&lt;</span>input
          type<span class="token operator">=</span><span class="token string">&quot;checkbox&quot;</span>
          checked<span class="token operator">=</span><span class="token punctuation">{</span>todo<span class="token punctuation">.</span>completed<span class="token punctuation">}</span>
          onChange<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>onToggleCompleted<span class="token punctuation">}</span>
        <span class="token operator">/</span><span class="token operator">&gt;</span>
        <span class="token punctuation">{</span>todo<span class="token punctuation">.</span>task<span class="token punctuation">}</span>
        <span class="token punctuation">{</span>todo<span class="token punctuation">.</span>assignee <span class="token operator">?</span> <span class="token operator">&lt;</span>small<span class="token operator">&gt;</span><span class="token punctuation">{</span>todo<span class="token punctuation">.</span>assignee<span class="token punctuation">.</span>name<span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>small<span class="token operator">&gt;</span> <span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">}</span>
        <span class="token operator">&lt;</span>RenderCounter <span class="token operator">/</span><span class="token operator">&gt;</span>
      <span class="token operator">&lt;</span><span class="token operator">/</span>li<span class="token operator">&gt;</span>
    <span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token function-variable function">onToggleCompleted</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> todo <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>todo
    todo<span class="token punctuation">.</span>completed <span class="token operator">=</span> <span class="token operator">!</span>todo<span class="token punctuation">.</span>completed
  <span class="token punctuation">}</span>

  <span class="token function-variable function">onRename</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> todo <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>todo
    todo<span class="token punctuation">.</span>task <span class="token operator">=</span> <span class="token function">prompt</span><span class="token punctuation">(</span><span class="token string">'Task name'</span><span class="token punctuation">,</span> todo<span class="token punctuation">.</span>task<span class="token punctuation">)</span> <span class="token operator">||</span> todo<span class="token punctuation">.</span>task
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span>
  <span class="token operator">&lt;</span>TodoList store<span class="token operator">=</span><span class="token punctuation">{</span>observableTodoStore<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
  document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'reactjs-app'</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span>
</code></pre></div><h3 id="常用-api"><a href="#常用-api" class="header-anchor">#</a> 常用 api</h3> <ol><li><p><code>@observable</code>装饰器, 装饰器可以在 ES7 或者 TypeScript 类属性中属性使用，将其转换成可观察的。@<code>observable</code>可以在实例字段和属性<code>getter</code>上使用。对于对象的哪部分需要成为可观察的，<code>@observable</code>提供了细粒度的控制。</p></li> <li><p><code>@computed</code>装饰器来声明式的创建计算属性。计算值(computed values)是可以根据现有的状态或其它计算值衍生出的值。概念上来说，它们与 excel 表格中的公式十分相似。不要低估计算值，因为它们有助于使实际可修改的状态尽可能的小。此外计算值还是高度优化过的，所以尽可能的多使用它们。<strong>不要把<code>computed</code>和<code>autorun</code>搞混</strong>。它们都是响应式调用的表达式，但是，<em>如果你想响应式的产生一个可以被其它 observer 使用的值，请使用 <code>@computed</code></em>，如果你<em>不想产生一个新值，而想要达到一个效果，请使用 <code>autorun</code></em>。举例来说，效果是像打印日志、发起网络请求等这样命令式的副作用。如果任何影响计算值的值发生变化了，计算值将根据状态自动进行衍生。计算值在大多数情况下可以被 MobX 优化的，因为它们被认为是纯函数。例如，如果前一个计算中使用的数据没有更改，计算属性将不会重新运行。如果某个其它计算属性或 reaction 未使用该计算属性，也不会重新运行。在这种情况下，它将被暂停。</p></li> <li><p><code>Autorun</code>自动运行。当你想创建一个响应式函数，而该函数本身永远不会有观察者时，可以使用<code>mobx.autorun</code>。 这通常是当你需要从反应式代码桥接到命令式代码的情况，例如打印日志、持久化或者更新 UI 的代码。 当使用 <code>autorun</code> 时，所提供的函数总是<strong>立即被触发一次</strong>，然后<strong>每次它的依赖关系改变时会再次被触发</strong>。 相比之下，<code>computed(function)</code> 创建的函数只有当它有自己的观察者时才会重新计算，否则它的值会被认为是不相关的。 经验法则：<strong>如果你有一个函数应该自动运行，但不会产生一个新的值，请使用<code>autorun</code>。 其余情况都应该使用 <code>computed</code></strong>。 Autoruns 是关于启动效果 (initiating effects) 的，而不是产生新的值。 如果字符串作为第一个参数传递给 autorun，它将被用作调试名。</p></li> <li><p><code>@observer</code>装饰器可以用来将 React 组件转变成响应式组件。 它用 <code>mobx.autorun</code> 包装了组件的 <code>render</code> 函数以确保任何组件渲染中使用的数据变化时都可以强制刷新组件。 <code>observer</code> 是由单独的 <code>mobx-react</code> 包提供的，所以需要这样导入它<code>import {observer} from &quot;mobx-react&quot;</code></p></li> <li><p><code>(@)action</code>动作,任何应用都有动作。动作是任何用来<strong>修改状态</strong>的东西。 使用 MobX 你可以在代码中显式地标记出动作所在的位置。 动作可以有助于更好的组织代码。它接收一个函数并返回具有同样签名的函数，但是用 transaction、untracked 和 allowStateChanges 包裹起来，尤其是 transaction 的自动应用会产生巨大的性能收益， 动作会分批处理变化并只在(最外层的)动作完成后通知计算值和反应。 这将确保在动作完成之前，在动作期间生成的中间值或未完成的值对应用的其余部分是不可见的。</p></li></ol></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">更新于:</span> <span class="time">5/4/2020, 9:17:46 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div>
    <script src="/assets/js/app.9e067b79.js" defer></script><script src="/assets/js/2.983eb755.js" defer></script><script src="/assets/js/18.3af7782b.js" defer></script>
  </body>
</html>
